package org.orm.oop.core.mapping;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.var;
import org.apache.commons.lang.StringUtils;
import org.orm.oop.api.Column;
import org.orm.oop.api.Id;
import org.orm.oop.api.Table;
import org.orm.oop.core.mapping.model.MappingXml;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;

/**
 * TODO 做缓存
 */
public class EntityResolveMappingXml {
    public static MappingXml entityResolveMapping(Class clazz) {
        MappingXml mappingXml = new MappingXml();

        resolveClassName(clazz, mappingXml);

        resolveTable(clazz, mappingXml);

        resolveDescription(clazz, mappingXml);

        resolveFields(clazz, mappingXml);

        return mappingXml;
    }

    static void resolveClassName(Class clazz, MappingXml mappingXml) {
        String className = clazz.getName();
        mappingXml.setClassName(className);
    }

    /**
     * @see org.orm.oop.api.Table
     */
    static void resolveTable(Class clazz, MappingXml mappingXml) {
        Table table = AnnotationUtils.getAnnotation(clazz, Table.class);
        if(table != null && StringUtils.isNotEmpty(table.name())) {
            mappingXml.setTable(table.name());
        }else {
            mappingXml.setTable(clazz.getSimpleName().toLowerCase());
        }
    }

    /**
     * @see Schema
     * @param clazz
     * @param mappingXml
     */
    static void resolveDescription(Class clazz, MappingXml mappingXml) {
        Schema schema = AnnotationUtils.getAnnotation(clazz, Schema.class);
        if(schema != null && StringUtils.isNotEmpty(schema.description())) {
            mappingXml.setDescription(schema.description());
        }
    }

    static void resolveFields(Class clazz, MappingXml mappingXml) {
        Field[] clazzFields = clazz.getDeclaredFields();
        for(var filed : clazzFields) {
            if(AnnotationUtils.getAnnotation(filed, Id.class) != null) {
                resolveId(filed, mappingXml);
            }else if(AnnotationUtils.getAnnotation(filed, Column.class) != null){
                resolveColumn(filed, mappingXml);
            }
        }
    }

    /**
     * @see Id
     * @param field
     * @param mappingXml
     */
    static void resolveId(Field field, MappingXml mappingXml) {
        Id id = AnnotationUtils.getAnnotation(field, Id.class);
        if(id != null) {
            if(!field.isAccessible()) field.setAccessible(true);

            MappingXml.ID idMapping = new MappingXml.ID();
            idMapping.setType(field.getType().getName());
            idMapping.setColumn(field.getName());
            idMapping.setName(field.getName());
            mappingXml.setId(idMapping);
        }
    }

    /**
     * @see Column
     * @param field
     * @param mappingXml
     */
    static void resolveColumn(Field field, MappingXml mappingXml) {
        Column column = AnnotationUtils.getAnnotation(field, Column.class);
        if(column != null) {
            if(!field.isAccessible()) field.setAccessible(true);

            MappingXml.Property propertyMapping = new MappingXml.Property();
            propertyMapping.setType(field.getType().getSimpleName().toLowerCase());
            propertyMapping.setColumn(field.getName());
            propertyMapping.setName(field.getName());

            if(mappingXml.getPropertyList() == null) mappingXml.setPropertyList(new ArrayList<>());
            mappingXml.getPropertyList().add(propertyMapping);
        }
    }
}
